﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GKQC.Common
{
    public class CpkTools
    {
        /// <summary>
        /// 计算标准偏差
        /// </summary>
        /// <param name="arrData"></param>
        /// <returns></returns>
        public static double StDev(double[] arrData) //计算标准偏差
        {
            double xSum = 0F;
            double xAvg = 0F;
            double sSum = 0F;
            double tmpStDev = 0F;
            int arrNum = arrData.Length;
            for (int i = 0; i < arrNum; i++)
            {
                xSum += arrData[i];
            }
            xAvg = xSum / arrNum;
            for (int j = 0; j < arrNum; j++)
            {
                sSum += ((arrData[j] - xAvg) * (arrData[j] - xAvg));
            }
            tmpStDev = Convert.ToSingle(Math.Sqrt((sSum / (arrNum - 1))).ToString());
            return tmpStDev;
        }
        private static double Cp(double UpperLimit, double LowerLimit, double StDev)//计算cp
        {
            double tmpV = 0F;
            tmpV = UpperLimit - LowerLimit;
            return Math.Abs(tmpV / (6 * StDev));
        }
        private static double Avage(double[] arrData)    //计算平均值
        {
            double tmpSum = 0F;
            for (int i = 0; i < arrData.Length; i++)
            {
                tmpSum += arrData[i];
            }
            return tmpSum / arrData.Length;
        }
        private static double Max(double[] arrData)   //计算最大值
        {
            double tmpMax = 0;
            for (int i = 0; i < arrData.Length; i++)
            {
                if (tmpMax < arrData[i])
                {
                    tmpMax = arrData[i];
                }
            }
            return tmpMax;
        }
        private static double Min(double[] arrData)  //计算最小值
        {
            double tmpMin = arrData[0];
            for (int i = 1; i < arrData.Length; i++)
            {
                if (tmpMin > arrData[i])
                {
                    tmpMin = arrData[i];
                }
            }
            return tmpMin;
        }
        private static double CpkU(double UpperLimit, double Avage, double StDev)//计算CpkU
        {
            double tmpV = 0F;
            tmpV = UpperLimit - Avage;
            return tmpV / (3 * StDev);
        }
        private static double CpkL(double LowerLimit, double Avage, double StDev) //计算CpkL
        {
            double tmpV = 0F;
            tmpV = Avage - LowerLimit;
            return tmpV / (3 * StDev);
        }
        private static double Cpk(double CpkU, double CpkL)  //计算Cpk
        {
            return Math.Min(CpkU, CpkL);
        }
        public static double getR_value(double[] k_valuesTOO)
        {
            double min = k_valuesTOO[0];
            double max = k_valuesTOO[0];
            for (int i = 0; i < k_valuesTOO.Length; i++)
            {
                if (k_valuesTOO[i] < min)
                {
                    min = k_valuesTOO[i];
                }
                if (k_valuesTOO[i] > max)
                {
                    max = k_valuesTOO[i];
                }
            }
            return max - min;
        }
        public static double GetCpk(double[] k, double UpperLimit, double LowerLimit) //获取CPK值
        {
            //CpkPro cpkPro = new CpkPro();
            //double[] k = { 0.03F, 0.06F, 0.05F, 0.03F, 0.04F, 0.04F, 0.03F, 0.04F, 0.04F, 0.04F, 0.04F, 0.04F, 0.04F, 0.03F, 0.01F, 0.03F, 0.01F, 0.03F, 0.04F, 0.04F, 0.04F, 0.05F, 0.02F, 0.04F, 0.05F, 0.05F, 0.05F, 0.05F, 0.03F, 0.05F, 0.05F, 0.03F, 0.02F, 0.04F, 0.04F, 0.02F, 0.06F, 0.04F, 0.02F, 0.03F, 0.04F, 0.02F, 0.05F, 0.06F, 0.07F, 0.02F, 0.04F, 0.04F, 0.03F, 0.03F };
            //double UpperLimit = 0.12F;  //上限
            //double LowerLimit = 0F; //下限
            //double result = cpkPro.getCPK(k, UpperLimit, LowerLimit);
            //Console.WriteLine(result);
            if (k.Length <= 1 || UpperLimit <= LowerLimit)
            {
                return -1;
            }
            double cpk = Math.Round(Cpk(CpkU(UpperLimit, Avage(k), StDev(k)), CpkL(LowerLimit, Avage(k), StDev(k))),2);
            return cpk;
        }

        public static double GetCpk(double[] k, double UpperLimit) //获取CPK值
        {
            double average = Avage(k);
            double stdev = StDev(k);
            double cpk = Math.Round(Math.Abs(UpperLimit - average) / (3 * stdev),2);
            return cpk;
        }

        public static string GetCpkLevel(double CPK)
        {
            string level = string.Empty;
            //显示Grade等级
            if (CPK < 0.67)
            {
                level = "E";
            }
            else
            {
                if (CPK < 1)
                {
                    level = "D";
                }
                else
                {
                    if (CPK < 1.33)
                    {
                        level = "C";
                    }
                    else
                    {
                        if (CPK < 1.67)
                        {
                            level = "B";
                        }
                        else
                        {
                            level = "A";
                        }

                    }

                }

            }

            return level;
        }
    }
}
